from mailbox import NotEmptyError
import time
from enum import Enum
import keyboard
import sys
import os
import re
################################################################
# 基础工具#
################################################################

# 事件机制


class Event():
    def __init__(self, name):
        self.name = name
        self.subscribers = []

    def subscribe(self, subscriber):
        self.subscribers.append(subscriber)

    def unsubscribe(self, subscriber):
        self.subscribers.remove(subscriber)

    def notify(self, *args, **kwargs):
        for subscriber in self.subscribers:
            subscriber(self, *args, **kwargs)


################################################################
################################################################

################################################################
# 游戏对象#
################################################################


class Zombie():
    def __init__(self):
        self.name = "僵尸"
        self.label = "尸"
        self.hp = 100
        self.maxhp = 100
        self.attack = 10
        self.attack_frequency_frame_taken = 10
        self.move_speed_per_frame = 1
        self.statu = ZombieStatu.idle


class ZombieStatu(Enum):
    idle = 0
    working = 1
    attacking = 2
    walking_and_attacking = 3


class Plant():
    def __init__(self):
        self.name = "植物"
        self.label = "植"
        self.hp = 100
        self.maxhp = 100
        self.cost = 100
        self.cd = 20
        self.use_key = "@"

    def action(self, *args, **kwargs):
        print("默认")


class Sunflower(Plant):
    def __init__(self,gm):
        self.name = "向日葵"
        self.label = "星"
        self.hp = 100
        self.maxhp = 100
        self.gm: GameManager=gm
        self.action_frequency_frame_taken = 100/self.gm.game_frame_speed  # todo 计算frame
        self.action_value = 25
        self.use_key = "h"
        self.cost = 50

    def action(self, *args, **kwargs):
        self.gm.sun_number += self.action_value


class hunter(Plant):
    def __init__(self,gm):
        self.name = "豌豆射手"
        self.label ="果"
        self.hp =100
        self.maxhp=100
        self.gm:GameManager=gm
        self.action_frequency_frame_taken =2/self.gm.game_frame_speed
        self.action_enable=False
        self.use_key="g"
        self.cost =100
        self.action_object_list =[]
        self.posistion_X =None
        self.posistion_Y =None

class Pea():
    def __init__(self,gm,ht):
        self.gm :GameManager=gm
        self.host:hunter=ht
        self.label = "一"
        self.action_speed_frame_taken =1/self.gm.game_frame_speed

################################################################
################################################################


################################################################
# 逻辑引擎#
################################################################


# 游戏管家
class GameManager():
    def __init__(self):
        # 游戏每帧速率-秒
        self.game_frame_speed = 0.1
        # 阳光掉落周期-秒（每过多少秒运行一次）
        self.drop_sun_frame_taken = 10/self.game_frame_speed
        # 游戏总帧率
        self.game_frame = 0
        # 阳光每周期掉落量
        self.sun_drop = 25
        # 阳光总数
        self.sun_number = 0
        # 植物对象表
        self.plant_list = []
        # 僵尸对象表
        self.zombie_list = []
        # 场景事件
        self.scene_event = Event("scene_event")
        # 玩家事件（主要是键盘操作）
        self.player_event = Event("player_event")
        # 植物事件
        self.plant_event = Event("plant_event")
        # 效果器事件（例如豌豆移动）
        self.filter_event = Event("filter_event")
        # 僵尸事件（僵尸移动）
        self.zombie_event = Event("zombie_event")
        # 上场的植物卡片
        self.plant_use = []
        # 拥有的植物卡片（还没有上场的，所有可选的卡片）
        self.plant_own = []
        # 上场的植物卡片的CD
        self.plant_cd = []
        # 场上每一行的地图行（用于绘制画面）
        self.row = []
        # 一次车对象表
        self.car = []
        # 结束fla-g为false时执行结束程序（主要没想到更好的结束方式）
        self.no_ending = True

    # 每过一段时间掉阳光
    def drop_sun(self, *args, **kwargs):

        if (self.game_frame % self.drop_sun_frame_taken == 0):
            self.sun_number += self.sun_drop

    # 计算阳光数量位数
    # 用于做对称界面
    def calculate_sun_digit(self):
        return len(str(self.sun_number))

    # 游戏结束
    def ending(self):
        self.no_ending = False


# 绘图者
class DrawWorker():
    def __init__(self, gm):
        self.item = ["", "", "", "", "", "", "", ""]
        self.item_timer = [0, 0, 0, 0, 0, 0, 0, 0]
        self.sun_num = "   0"
        self.slot0 = "    "
        self.slot = "【     】【     】【     】【     】【     】【     】【     】【     】【铲   】"
        self.slot_label = "【h   0】【j   0】【k   0】【l   0】【y   0】【u   0】【i   0】【o   0】【;    】"
        self.car = ["車", "車", "車", "車", "車"]
        self.row = ["", "", "", "", ""]
        self.history = ["1", "h2", "je2", "kc", "u3c", ";b1"]
        self.opt = ""
        self.gm: GameManager = gm

    # 绘制阳光数
    def draw_sun_num(self):
        self.sun_num = str(self.gm.sun_number)

    # 与阳光数对称用的
    def draw_slot0(self):
        self.slot0 = " "*self.gm.calculate_sun_digit()

    # 绘制卡片槽
    def draw_slot_and_slot_lable(self):
        self.slot = ""
        self.slot_label = ""
        plant_use = self.gm.plant_use
        plant_cd = self.gm.plant_cd
        for i in range(8):
            self.slot += f"【{plant_use[i].label}{str(plant_cd[i]).rjust(3)}】"
            self.slot_label += f"【{plant_use[i].use_key}{str(plant_use[i].cost).rjust(4)}】"
        self.slot += "【铲   】"
        self.slot_label += "【;    】"

    # 绘制主界面

    def draw_ui(self):
        self.draw_slot0()
        self.draw_sun_num()
        self.draw_slot_and_slot_lable()

        print(f'''游戏时间{self.gm.game_frame}
日{self.sun_num} {self.slot}
  {self.slot0} {self.slot_label}
     
     ┏      ┳      ┳      ┳      ┳      ┳      ┳      ┓
a {self.car[0]}  {self.row[0]}
     ┣      ╋      ╋      ╋      ╋      ╋      ╋      ┫
b {self.car[1]}  {self.row[1]}
     ┣      ╋      ╋      ╋      ╋      ╋      ╋      ┫
c {self.car[2]}  {self.row[2]}
     ┣      ╋      ╋      ╋      ╋      ╋      ╋      ┫
d {self.car[3]}  {self.row[3]}
     ┣      ╋      ╋      ╋      ╋      ╋      ╋      ┫
e {self.car[4]}  {self.row[4]}
     ┗      ┻      ┻      ┻      ┻      ┻      ┻      ┛
         1      2     3       4      5      6      7
{self.history}
[操作]:{self.opt}
            ''')

    # 绘制正在输入的操作字符
    def operation_add(self, key):
        self.opt += key


    # 重置正在输入的操作字符
    def operation_clear(self):
        self.operation_check()
        self.opt = ""
        #

    # 检查输入操作正不正确，正确则执行
    def operation_check(self):
        pattern_collect_sun=r'^[1-7]$'
        pattern_buy=r'^[h-pH-P;]([1-7]?[a-fA-F]?|[a-fA-F]?[1-7]?)$'
        if(re.match(pattern_collect_sun,self.opt)):
            # 捡阳光
            self.operation_pick_sun()
        
        elif(re.match(pattern_buy,self.opt)):
            # 种植
            self.operation_do_plant()

    def operation_pick_sun(self):
        
    # 种植
    def operation_do_plant(self):


    #   ["星", "果", "圃", "火", "包", "皿", "瓜", ""]


################################################################
################################################################


################################################################
# 游戏进程#
################################################################

# timer
gm = GameManager()
dw = DrawWorker(gm)

gm.plant_use = [Sunflower(gm), hunter(gm), Plant(), Plant(), Plant(), Plant(), Plant(), Plant()]
gm.plant_cd = [" ", " ", " ", " ", " ", " ", " ", " ", " "]


gm.scene_event.subscribe(gm.drop_sun)


# 按键绑定
for i in range(97, 123):
    if i == 113:  # 按q退出
        keyboard.add_hotkey(chr(i), gm.ending)
        break
    keyboard.add_hotkey(chr(i), lambda x=i: dw.operation_add(chr(x)))


for i in range(49, 58):
    keyboard.add_hotkey(chr(i), lambda x=i: dw.operation_add(chr(x)))

keyboard.add_hotkey("space", dw.operation_clear)


# 游戏运行每个循环为1帧
while gm.no_ending:
    # 清屏
    os.system("cls")
    # 游戏总帧数没循环+1
    gm.game_frame += 1
    gm.scene_event.notify("运行场景事件")
    gm.player_event .notify("运行玩家事件")
    gm.plant_event  .notify("运行植物事件")
    gm.filter_event .notify("运行效果器事件")
    gm.zombie_event .notify("运行僵尸事件")

    dw.draw_ui()
    time.sleep(gm.game_frame_speed)


################################################################
################################################################
